import EventListenerHelper from './eventListener';
import { parseDuration } from '../common/helpers';
import { debounce } from '../flow/timing';

/**
 * 变换类型枚举
 */
export enum TransformType {
  MOVE = 'move',
  ROTATE = 'rotate',
  SCALE = 'scale',
  SKEW = 'skew',
  FLIP = 'flip'
}

/**
 * 触发方式枚举
 */
export enum TriggerType {
  CLICK = 'click',
  HOVER = 'hover',
  DOUBLE_CLICK = 'dblclick',
  MOUSE_ENTER = 'mouseenter',
  MOUSE_LEAVE = 'mouseleave',
  AUTO = 'auto'
}

/**
 * 移动方向枚举
 */
export enum MoveDirection {
  UP = 'up',
  DOWN = 'down',
  LEFT = 'left',
  RIGHT = 'right'
}

/**
 * 变换配置接口
 */
export interface TransformAction {
  type: TransformType;
  trigger: TriggerType;
  params: any[];
  duration?: number | string;
  timingFunction?: string;
}

/**
 * 变换队列项接口
 */
interface TransformQueueItem {
  action: TransformAction;
  resolve: () => void;
}

/**
 * 元素变换状态接口
 */
interface ElementTransformState {
  isAnimating: boolean;
  queue: TransformQueueItem[];
  originalStyle: Record<string, string>;
  currentTransform: string;
  eventListeners: Array<{ event: string, listener: EventListener }>;
  // 存储当前变换的具体状态，用于累积变换
  transformValues: {
    translateX: number;
    translateY: number;
    rotate: number;
    scaleX: number;
    scaleY: number;
    skewX: number;
    skewY: number;
    flipHorizontal: boolean;
    flipVertical: boolean;
  };
}

/**
 * 通用变换管理类
 * @description 用于管理DOM元素的CSS变换效果，支持链式调用和顺序执行
 */
export class TransformManager {
  // 存储每个元素的变换状态
  private static __elementStates: WeakMap<HTMLElement, ElementTransformState> = new WeakMap();

  // 当前操作的元素和变换队列
  private __element: HTMLElement | null = null;
  private __transformQueue: TransformAction[] = [];

  // 为每个触发器类型维护一个独立的队列
  private __triggerActionMap: Map<string, TransformAction[]> = new Map();
  // 为每个触发器类型维护一个当前执行索引
  private __triggerIndexMap: Map<string, number> = new Map();

  // 事件监听帮助类实例
  private __eventListenerHelper: EventListenerHelper = new EventListenerHelper();

  // 静态枚举属性，便于通过类访问
  public static TransformType = TransformType;
  public static TriggerType = TriggerType;
  public static MoveDirection = MoveDirection;

  /**
   * 创建TransformManager实例
   * @param {HTMLElement} element - 要操作的DOM元素
   * @returns {TransformManager} TransformManager实例
   */
  static of(element: HTMLElement): TransformManager {
    const manager = new TransformManager();
    manager.__element = element;

    // 初始化元素状态
    if (!this.__elementStates.has(element)) {
      this.__elementStates.set(element, {
        isAnimating: false,
        queue: [],
        originalStyle: {},
        currentTransform: '',
        eventListeners: [],
        transformValues: {
          translateX: 0,
          translateY: 0,
          rotate: 0,
          scaleX: 1,
          scaleY: 1,
          skewX: 0,
          skewY: 0,
          flipHorizontal: false,
          flipVertical: false
        }
      });
    }

    return manager;
  }

  /**
   * 移动元素
   * @param {MoveDirection | string} direction - 移动方向
   * @param {number | string} distance - 移动距离
   * @param {TriggerType | string} trigger - 触发方式
   * @param {number | string} duration - 动画持续时间
   * @param {string} timingFunction - 动画时间函数
   * @returns {TransformManager} 当前实例，支持链式调用
   */
  move(
    direction: MoveDirection | string,
    distance: number | string,
    trigger: TriggerType | string = TriggerType.AUTO,
    duration: number | string = '0.5s',
    timingFunction: string = 'ease'
  ): TransformManager {
    this.__transformQueue.push({
      type: TransformType.MOVE,
      trigger: trigger as TriggerType,
      params: [direction, distance],
      duration,
      timingFunction
    });
    return this;
  }

  /**
   * 旋转元素
   * @param {string} origin - 旋转原点
   * @param {number | string} angle - 旋转角度
   * @param {TriggerType | string} trigger - 触发方式
   * @param {number | string} duration - 动画持续时间
   * @param {string} timingFunction - 动画时间函数
   * @returns {TransformManager} 当前实例，支持链式调用
   */
  rotate(
    origin: string = 'center',
    angle: number | string,
    trigger: TriggerType | string = TriggerType.AUTO,
    duration: number | string = '0.5s',
    timingFunction: string = 'ease'
  ): TransformManager {
    this.__transformQueue.push({
      type: TransformType.ROTATE,
      trigger: trigger as TriggerType,
      params: [origin, angle],
      duration,
      timingFunction
    });
    return this;
  }

  /**
   * 缩放元素
   * @param {number | string} scaleX - X轴缩放比例
   * @param {number | string} scaleY - Y轴缩放比例
   * @param {TriggerType | string} trigger - 触发方式
   * @param {number | string} duration - 动画持续时间
   * @param {string} timingFunction - 动画时间函数
   * @returns {TransformManager} 当前实例，支持链式调用
   */
  scale(
    scaleX: number | string,
    scaleY: number | string = scaleX,
    trigger: TriggerType | string = TriggerType.AUTO,
    duration: number | string = '0.5s',
    timingFunction: string = 'ease'
  ): TransformManager {
    this.__transformQueue.push({
      type: TransformType.SCALE,
      trigger: trigger as TriggerType,
      params: [scaleX, scaleY],
      duration,
      timingFunction
    });
    return this;
  }

  /**
   * 倾斜元素
   * @param {number | string} skewX - X轴倾斜角度
   * @param {number | string} skewY - Y轴倾斜角度
   * @param {TriggerType | string} trigger - 触发方式
   * @param {number | string} duration - 动画持续时间
   * @param {string} timingFunction - 动画时间函数
   * @returns {TransformManager} 当前实例，支持链式调用
   */
  skew(
    skewX: number | string,
    skewY: number | string = 0,
    trigger: TriggerType | string = TriggerType.AUTO,
    duration: number | string = '0.5s',
    timingFunction: string = 'ease'
  ): TransformManager {
    this.__transformQueue.push({
      type: TransformType.SKEW,
      trigger: trigger as TriggerType,
      params: [skewX, skewY],
      duration,
      timingFunction
    });
    return this;
  }

  /**
   * 翻转元素
   * @param {string} direction - 翻转方向 ('horizontal' 或 'vertical')
   * @param {TriggerType | string} trigger - 触发方式
   * @param {number | string} duration - 动画持续时间
   * @param {string} timingFunction - 动画时间函数
   * @returns {TransformManager} 当前实例，支持链式调用
   */
  flip(
    direction: string = 'horizontal',
    trigger: TriggerType | string = TriggerType.AUTO,
    duration: number | string = '0.5s',
    timingFunction: string = 'ease'
  ): TransformManager {
    this.__transformQueue.push({
      type: TransformType.FLIP,
      trigger: trigger as TriggerType,
      params: [direction],
      duration,
      timingFunction
    });
    return this;
  }

  /**
   * 执行变换队列
   * @returns {void}
   */
  execute(): void {
    if (!this.__element) return;

    const state = TransformManager.__elementStates.get(this.__element);
    if (!state) return;

    // 为每个触发器类型组织动作队列
    this.__transformQueue.forEach(action => {
      if (action.trigger === TriggerType.AUTO) {
        // 自动触发，立即加入队列
        this.__addToQueue(this.__element!, action);
      } else {
        // 为该触发器类型初始化队列和索引
        if (!this.__triggerActionMap.has(action.trigger)) {
          this.__triggerActionMap.set(action.trigger, []);
          this.__triggerIndexMap.set(action.trigger, 0);
          // 只添加一次事件监听器
          this.__setupEventListener(this.__element!, action.trigger);
        }
        // 将动作添加到对应触发器的队列中
        this.__triggerActionMap.get(action.trigger)!.push(action);
      }
    });

    // 清空队列
    this.__transformQueue = [];
  }

  /**
   * 设置事件监听器
   * @param {HTMLElement} element - DOM元素
   * @param {string} trigger - 触发类型
   * @returns {void}
   */
  private __setupEventListener(element: HTMLElement, trigger: string): void {
    const state = TransformManager.__elementStates.get(element);
    if (!state) return;

    // 获取该触发器类型的动作队列
    const actions = this.__triggerActionMap.get(trigger);

    // 计算当前触发器类型的最大变换时间（作为防抖时间）
    let maxDuration = 500; // 默认值
    if (actions && actions.length > 0) {
      maxDuration = Math.max(...actions.map(action => parseDuration(action.duration)));
    }

    // 处理不同类型的触发器
    if (trigger === TriggerType.HOVER) {
      // HOVER触发器需要特殊处理，使用mouseenter和mouseleave事件

      // 存储元素变换前的状态，用于mouseleave时恢复
      const originalTransformValues = {
        translateX: 0,
        translateY: 0,
        rotate: 0,
        scaleX: 1,
        scaleY: 1,
        skewX: 0,
        skewY: 0,
        flipHorizontal: false,
        flipVertical: false
      };

      // 鼠标进入事件处理 - 添加防抖
      const mouseEnterHandler = () => {
        // 获取该触发器类型的动作队列和当前索引
        const actions = this.__triggerActionMap.get(trigger);
        if (!actions) return;

        // 保存原始状态
        if (state.transformValues) {
          Object.assign(originalTransformValues, state.transformValues);
        }

        // 如果当前没有动画在执行，才开始执行动作
        if (!state.isAnimating) {
          // 获取当前索引
          let index = this.__triggerIndexMap.get(trigger) || 0;

          // 确保索引在有效范围内
          if (index < actions.length) {
            const action = actions[index];
            this.__addToQueue(element, action).then(() => {
              // 动作执行完成后，索引加1
              this.__triggerIndexMap.set(trigger, index + 1);

              // 如果所有动作都已执行，重置索引以便循环执行
              if (index + 1 >= actions.length) {
                this.__triggerIndexMap.set(trigger, 0);
              }
            });
          }
        }
      };

      // 鼠标离开事件处理 - 添加防抖
      const mouseLeaveHandler = () => {
        // 当鼠标离开时，只清空队列，不重置变换状态
        if (state) {
          // 清空队列，防止残留动作继续执行
          state.queue = [];
          state.isAnimating = false;

          // 不重置元素状态，保持当前变换效果
        }
      };

      // 应用防抖函数 - 防抖时间与当前事件的变换时间一致
      const mouseEnterListener = debounce(mouseEnterHandler, maxDuration, true);
      const mouseLeaveListener = debounce(mouseLeaveHandler, maxDuration);

      // 使用EventListenerHelper添加hover事件监听
      this.__eventListenerHelper.addHoverListener(element, {
        onMouseEnter: mouseEnterListener,
        onMouseLeave: mouseLeaveListener
      });

      // 保存事件监听器以便后续清理
      state.eventListeners.push(
        { event: 'mouseenter', listener: mouseEnterListener },
        { event: 'mouseleave', listener: mouseLeaveListener }
      );
    } else {
      // 处理其他类型的触发器
      const eventHandler = (event: Event) => {
        event.preventDefault();

        // 获取该触发器类型的动作队列和当前索引
        const actions = this.__triggerActionMap.get(trigger);
        if (!actions) return;

        let index = this.__triggerIndexMap.get(trigger) || 0;

        // 如果还有未执行的动作，则执行下一个
        if (index < actions.length) {
          const action = actions[index];
          this.__addToQueue(element, action).then(() => {
            // 动作执行完成后，索引加1，为下一次触发做准备
            this.__triggerIndexMap.set(trigger, index + 1);

            // 如果所有动作都已执行，重置索引以便循环执行
            if (index + 1 >= actions.length) {
              this.__triggerIndexMap.set(trigger, 0);
            }
          });
        }
      };

      // 应用防抖函数 - 防抖时间与当前事件的变换时间一致
      const eventListener = debounce(eventHandler, maxDuration, true);

      // 使用EventListenerHelper添加普通事件监听
      this.__eventListenerHelper.addListener(element, trigger, eventListener);

      // 保存事件监听器以便后续清理
      state.eventListeners.push({ event: trigger, listener: eventListener });
    }
  }

  /**
   * 将变换添加到队列
   * @param {HTMLElement} element - DOM元素
   * @param {TransformAction} action - 变换动作
   * @returns {Promise<void>} 变换完成的Promise
   */
  private __addToQueue(element: HTMLElement, action: TransformAction): Promise<void> {
    return new Promise((resolve) => {
      const state = TransformManager.__elementStates.get(element);
      if (!state) return resolve();

      state.queue.push({ action, resolve });

      // 如果当前没有动画在执行，则开始执行队列
      if (!state.isAnimating) {
        this.__processQueue(element);
      }
    });
  }

  /**
   * 处理变换队列
   * @param {HTMLElement} element - DOM元素
   * @returns {void}
   */
  private __processQueue(element: HTMLElement): void {
    const state = TransformManager.__elementStates.get(element);
    if (!state || state.queue.length === 0) return;

    state.isAnimating = true;
    const queueItem = state.queue.shift();
    if (!queueItem) {
      state.isAnimating = false;
      return;
    }

    const { action, resolve } = queueItem;

    // 应用变换
    this.__applyTransform(element, action).then(() => {
      // 变换完成后解析Promise
      resolve();

      // 继续处理下一个变换
      state.isAnimating = false;
      this.__processQueue(element);
    });
  }

  /**
   * 应用具体的变换
   * @param {HTMLElement} element - DOM元素
   * @param {TransformAction} action - 变换动作
   * @returns {Promise<void>} 变换完成的Promise
   */
  private __applyTransform(element: HTMLElement, action: TransformAction): Promise<void> {
    return new Promise((resolve) => {
      // 保存原始样式
      const originalTransition = element.style.transition;

      // 设置过渡效果
      element.style.transition = `transform ${action.duration} ${action.timingFunction}`;

      // 应用具体变换
      switch (action.type) {
        case TransformType.MOVE:
          this.__applyMove(element, action.params[0], action.params[1]);
          break;
        case TransformType.ROTATE:
          this.__applyRotate(element, action.params[0], action.params[1]);
          break;
        case TransformType.SCALE:
          this.__applyScale(element, action.params[0], action.params[1]);
          break;
        case TransformType.SKEW:
          this.__applySkew(element, action.params[0], action.params[1]);
          break;
        case TransformType.FLIP:
          this.__applyFlip(element, action.params[0]);
          break;
      }

      // 监听过渡结束事件
      const handleTransitionEnd = () => {
        element.removeEventListener('transitionend', handleTransitionEnd);

        // 恢复原始过渡样式
        element.style.transition = originalTransition;

        // 解析Promise表示变换完成
        resolve();
      };

      element.addEventListener('transitionend', handleTransitionEnd);

      // 添加超时处理，以防transitionend事件未触发
      setTimeout(() => {
        element.removeEventListener('transitionend', handleTransitionEnd);
        element.style.transition = originalTransition;
        resolve();
      }, this.__getDurationInMs(action.duration) + 100);
    });
  }

  /**
   * 应用移动变换
   * @param {HTMLElement} element - DOM元素
   * @param {MoveDirection | string} direction - 移动方向
   * @param {number | string} distance - 移动距离
   * @returns {void}
   */
  private __applyMove(element: HTMLElement, direction: MoveDirection | string, distance: number | string): void {
    const state = TransformManager.__elementStates.get(element);
    if (!state) return;

    // 解析距离值
    const distanceNum = typeof distance === 'number' ? distance : parseFloat(distance);

    // 根据方向更新当前位置
    switch (direction) {
      case MoveDirection.UP:
        state.transformValues.translateY -= distanceNum;
        break;
      case MoveDirection.DOWN:
        state.transformValues.translateY += distanceNum;
        break;
      case MoveDirection.LEFT:
        state.transformValues.translateX -= distanceNum;
        break;
      case MoveDirection.RIGHT:
        state.transformValues.translateX += distanceNum;
        break;
    }

    // 应用累积变换
    this.__applyCumulativeTransform(element);
  }

  /**
   * 应用旋转变换
   * @param {HTMLElement} element - DOM元素
   * @param {string} origin - 旋转原点
   * @param {number | string} angle - 旋转角度
   * @returns {void}
   */
  private __applyRotate(element: HTMLElement, origin: string, angle: number | string): void {
    const state = TransformManager.__elementStates.get(element);
    if (!state) return;

    element.style.transformOrigin = origin;

    // 解析角度值并累加到当前旋转角度
    const angleNum = typeof angle === 'number' ? angle : parseFloat(angle);
    state.transformValues.rotate += angleNum;

    // 应用累积变换
    this.__applyCumulativeTransform(element);
  }

  /**
   * 应用缩放变换
   * @param {HTMLElement} element - DOM元素
   * @param {number | string} scaleX - X轴缩放比例
   * @param {number | string} scaleY - Y轴缩放比例
   * @returns {void}
   */
  private __applyScale(element: HTMLElement, scaleX: number | string, scaleY: number | string): void {
    const state = TransformManager.__elementStates.get(element);
    if (!state) return;

    // 解析缩放比例并更新当前缩放值
    const scaleXNum = typeof scaleX === 'number' ? scaleX : parseFloat(scaleX);
    const scaleYNum = typeof scaleY === 'number' ? scaleY : parseFloat(scaleY);

    state.transformValues.scaleX = scaleXNum;
    state.transformValues.scaleY = scaleYNum;

    // 应用累积变换
    this.__applyCumulativeTransform(element);
  }

  /**
   * 应用倾斜变换
   * @param {HTMLElement} element - DOM元素
   * @param {number | string} skewX - X轴倾斜角度
   * @param {number | string} skewY - Y轴倾斜角度
   * @returns {void}
   */
  private __applySkew(element: HTMLElement, skewX: number | string, skewY: number | string): void {
    const state = TransformManager.__elementStates.get(element);
    if (!state) return;

    // 解析倾斜角度并更新当前倾斜值
    const skewXNum = typeof skewX === 'number' ? skewX : parseFloat(skewX);
    const skewYNum = typeof skewY === 'number' ? skewY : parseFloat(skewY);

    state.transformValues.skewX = skewXNum;
    state.transformValues.skewY = skewYNum;

    // 应用累积变换
    this.__applyCumulativeTransform(element);
  }

  /**
   * 应用翻转变换
   * @param {HTMLElement} element - DOM元素
   * @param {string} direction - 翻转方向
   * @returns {void}
   */
  private __applyFlip(element: HTMLElement, direction: string): void {
    const state = TransformManager.__elementStates.get(element);
    if (!state) return;

    // 更新翻转状态
    if (direction === 'horizontal') {
      state.transformValues.flipHorizontal = !state.transformValues.flipHorizontal;
    } else if (direction === 'vertical') {
      state.transformValues.flipVertical = !state.transformValues.flipVertical;
    }

    // 应用累积变换
    this.__applyCumulativeTransform(element);
  }

  /**
   * 将持续时间转换为毫秒
   * @param {number | string} duration - 持续时间
   * @returns {number} 毫秒数
   */
  private __getDurationInMs(duration?: number | string): number {
    // 如果duration是undefined，返回默认值
    if (duration === undefined) {
      return 500;
    }

    if (typeof duration === 'number') {
      return duration;
    }

    // 处理字符串格式的时间，如 '0.5s' 或 '500ms'
    const match = duration.match(/^(\d+(\.\d+)?)([sm])$/);
    if (match) {
      const value = parseFloat(match[1]);
      const unit = match[3];
      return unit === 's' ? value * 1000 : value;
    }

    // 默认返回500毫秒
    return 500;
  }

  /**
   * 应用累积变换
   * @param {HTMLElement} element - DOM元素
   * @returns {void}
   */
  private __applyCumulativeTransform(element: HTMLElement): void {
    const state = TransformManager.__elementStates.get(element);
    if (!state) return;

    // 构建累积变换字符串
    let transformString = '';

    // 应用平移
    if (state.transformValues.translateX !== 0 || state.transformValues.translateY !== 0) {
      transformString += `translate(${state.transformValues.translateX}px, ${state.transformValues.translateY}px) `;
    }

    // 应用旋转
    if (state.transformValues.rotate !== 0) {
      transformString += `rotate(${state.transformValues.rotate}deg) `;
    }

    // 应用缩放（考虑翻转）
    let effectiveScaleX = state.transformValues.scaleX;
    let effectiveScaleY = state.transformValues.scaleY;

    if (state.transformValues.flipHorizontal) {
      effectiveScaleX *= -1;
    }
    if (state.transformValues.flipVertical) {
      effectiveScaleY *= -1;
    }

    if (effectiveScaleX !== 1 || effectiveScaleY !== 1) {
      transformString += `scale(${effectiveScaleX}, ${effectiveScaleY}) `;
    }

    // 应用倾斜
    if (state.transformValues.skewX !== 0 || state.transformValues.skewY !== 0) {
      transformString += `skew(${state.transformValues.skewX}deg, ${state.transformValues.skewY}deg) `;
    }

    // 去除末尾空格并应用变换
    transformString = transformString.trim();
    element.style.transform = transformString || 'none';

    // 保存当前变换字符串
    state.currentTransform = transformString;
  }

  /**
   * 清除元素的所有变换和事件监听器
   * @param {HTMLElement} [element] - DOM元素，如果不提供则清除当前操作的元素
   * @returns {void}
   */
  clear(element?: HTMLElement): void {
    const targetElement = element || this.__element;
    if (!targetElement) return;

    // 使用EventListenerHelper清理事件监听器
    this.__eventListenerHelper.clear(targetElement);

    // 调用静态clear方法完成其他清理工作
    TransformManager.clear(targetElement);
  }

  /**
   * 清除元素的所有变换和事件监听器（静态方法）
   * @param {HTMLElement} element - DOM元素
   * @returns {void}
   */
  static clear(element: HTMLElement): void {
    const state = this.__elementStates.get(element);
    if (!state) return;

    // 移除所有事件监听器
    state.eventListeners.forEach(({ event, listener }) => {
      element.removeEventListener(event, listener);
    });

    // 重置变换样式
    element.style.transform = '';
    element.style.transition = '';
    element.style.transformOrigin = '';

    // 清除状态
    this.__elementStates.delete(element);
  }
}